Send trait
/mrsekut-book-4065301955/102
gpt-5.icon
Rust の Send トレイトは、
ある型の値を “別スレッドへ安全にムーブできるか” を表すマーカートレイト
です。
かなり重要なので、要点→仕組み→具体例の順で説明します。
結論(まずこれ)
Send が実装されている型は スレッド間で所有権ごと移動できる
Rust は コンパイル時に Send かどうかをチェックする
ほとんどの型は自動的に Send になる
内部にスレッド非安全なものを持つと Send にならない
定義は超シンプル:
code:rust
pub unsafe auto trait Send {}
中身は空で、「性質」だけを表します。
何のためにある?
マルチスレッドでこんなコードを書くとき:
code:rust
std::thread::spawn(move || {
// ここで x を使う
});
この move によってクロージャへ値が渡されます。
このとき Rust は:
「その値、本当に別スレッドに送って大丈夫?」
を Send で判定します。
もし Send じゃなければ コンパイルエラーになります。
つまり:
👉 データ競合を“実行前に”殺す仕組み
です。
自動実装(auto trait)
Send は auto trait なので:
code:rust
struct MyType {
a: i32,
b: String,
}
みたいな型は、
i32: Send
String: Send
なので
→ MyType も自動的に Send
になります。
ルールは:
すべてのフィールドが Send なら、その型も Send
Send にならない代表例
典型はこれ:
code:rust
use std::rc::Rc;
let x = Rc::new(5);
Rc<T> は Send ではありません。
理由:
参照カウントを atomic にしていない
複数スレッドで壊れる可能性がある
なので:
code:rust
thread::spawn(move || {
println!("{}", x);
});
→ コンパイルエラー。
代わりに使うのが:
code:rust
use std::sync::Arc;
Arc は atomic reference count なので Send。
Send と Sync の違い(重要)
よくセットで出てくるので整理します:
table:_
trait 意味
Send 所有権を別スレッドへ渡せる
Sync 参照を別スレッドで共有できる
イメージ:
Send → move OK
Sync → &T OK
例:
Arc<T> → Send + Sync
Rc<T> → どちらも NO
unsafe auto trait な理由
Send は:
code:rust
unsafe auto trait Send {}
つまり:
基本はコンパイラが自動判定
手動実装するなら unsafe impl Send
になります。
理由は:
👉 間違えると即 UB(未定義動作)だから。
ほぼ 自分で impl しない と思ってOKです。
まとめ
Send = 「この型は別スレッドに投げていい」
Rust のスレッド安全性の中核
フィールド全部 Send → 自動で Send
Rc みたいな非 atomic な型は Send じゃない
マルチスレッドで move するとき必ずチェックされる